#include <gtest/gtest.h>
#include <memory>
#include"PoseEq.hpp"
#include "Executor.hpp"

namespace adas
{
// bool operator==(const Pose& lhs, const Pose& rhs)
// {  // 为Pose定义==运算符重载，使得在测试中比较Pose对象变得简单明了， std::tie提高代码可读性
//     return std::tie(lhs.x, lhs.y, lhs.heading) == std::tie(rhs.x, rhs.y, rhs.heading);
// }
// 测试化用例1：初始化车的位置和方向
TEST(ExecutorTest, should_return_init_pose_when_without_command)
{
    // given
    std::unique_ptr<Executor> executor(Executor::NewExecutor({0, 0, 'E'}, CarsType::CAR));
    // when

    // then
    const Pose target({0, 0, 'E'});
    ASSERT_EQ(target, executor->Query());
}
// 测试化用例2：未初始化车的位置和方向，查询接口返回默认值
TEST(ExecutorTest, should_return_default_pose_when_without_init_and_command)
{
    // given
    std::unique_ptr<Executor> executor(Executor::NewExecutor());
    // when

    // then
    const Pose target({0, 0, 'N'});
    ASSERT_EQ(target, executor->Query());
}
// 测试化用例3：向东走1步
TEST(ExecutorTest, should_return_x_plus_1_given_command_is_M_and_facing_is_E)
{
    // given
    std::unique_ptr<Executor> executor(Executor::NewExecutor({0, 0, 'E'}, CarsType::CAR));
    // when
    executor->Execute("M");
    // then
    const Pose target({1, 0, 'E'});
    ASSERT_EQ(target, executor->Query());
}
// 测试化用例4：向西走1步
TEST(ExecutorTest, should_return_x_minus_1_given_command_is_M_and_facing_is_W)
{
    // given
    std::unique_ptr<Executor> executor(Executor::NewExecutor({0, 0, 'W'}, CarsType::CAR));

    // when
    executor->Execute("M");

    // then
    const Pose target({-1, 0, 'W'});
    ASSERT_EQ(target, executor->Query());
}
//测试化用例4：向北走一步
TEST(ExecutorTest, should_return_y_plus_1_given_command_is_M_and_facing_is_N)
{
    // given
    std::unique_ptr<Executor> executor(Executor::NewExecutor({0, 0, 'N'}, CarsType::CAR));

    // when
    executor->Execute("M");

    // then
    const Pose target({0, 1, 'N'});
    ASSERT_EQ(target, executor->Query());
}
// 测试化用例5：向南走一步
TEST(ExecutorTest, should_return_y_minus_1_given_command_is_M_and_facing_is_S)
{
    // given
    std::unique_ptr<Executor> executor(Executor::NewExecutor({0, 0, 'S'}, CarsType::CAR));

    // when
    executor->Execute("M");

    // then
    const Pose target({0, -1, 'S'});
    ASSERT_EQ(target, executor->Query());
}
//测试化用例6：向东左转为北
TEST(ExecutorTest, should_return_facing_is_N_given_command_is_L_and_facing_is_E)
{
    // given
    std::unique_ptr<Executor> executor(Executor::NewExecutor({0, 0, 'E'}, CarsType::CAR));

    // when
    executor->Execute("L");

    // then
    const Pose target({0, 0, 'N'});
    ASSERT_EQ(target, executor->Query());
}
//测试化用例7：向西左转为南
TEST(ExecutorTest, should_return_facing_is_S_given_command_is_L_and_facing_is_W)
{
    // given
    std::unique_ptr<Executor> executor(Executor::NewExecutor({0, 0, 'W'}, CarsType::CAR));

    // when
    executor->Execute("L");

    // then
    const Pose target({0, 0, 'S'});
    ASSERT_EQ(target, executor->Query());
}
//测试化用例8：向北左转为西
TEST(ExecutorTest, should_return_facing_is_W_given_command_is_L_and_facing_is_N)
{
    // given
    std::unique_ptr<Executor> executor(Executor::NewExecutor({0, 0, 'N'}, CarsType::CAR));

    // when
    executor->Execute("L");

    // then
    const Pose target({0, 0, 'W'});
    ASSERT_EQ(target, executor->Query());
}
//测试化用例9：向南左转为东
TEST(ExecutorTest, should_return_facing_is_E_given_command_is_L_and_facing_is_S)
{
    // given
    std::unique_ptr<Executor> executor(Executor::NewExecutor({0, 0, 'S'}, CarsType::CAR));

    // when
    executor->Execute("L");

    // then
    const Pose target({0, 0, 'E'});
    ASSERT_EQ(target, executor->Query());
}
//测试化用例10：向东右转为南
TEST(ExecutorTest, should_return_facing_is_S_given_command_is_R_and_facing_is_E)
{
    // given
    std::unique_ptr<Executor> executor(Executor::NewExecutor({0, 0, 'E'}, CarsType::CAR));

    // when
    executor->Execute("R");

    // then
    const Pose target({0, 0, 'S'});
    ASSERT_EQ(target, executor->Query());
}
//测试化用例11：向西右转为北
TEST(ExecutorTest, should_return_facing_is_N_given_command_is_R_and_facing_is_W)
{
    // given
    std::unique_ptr<Executor> executor(Executor::NewExecutor({0, 0, 'W'}, CarsType::CAR));

    // when
    executor->Execute("R");

    // then
    const Pose target({0, 0, 'N'});
    ASSERT_EQ(target, executor->Query());
}
//测试化用例12：向北右转为东
TEST(ExecutorTest, should_return_facing_is_E_given_command_is_R_and_facing_is_N)
{
    // given
    std::unique_ptr<Executor> executor(Executor::NewExecutor({0, 0, 'N'}, CarsType::CAR));

    // when
    executor->Execute("R");

    // then
    const Pose target({0, 0, 'E'});
    ASSERT_EQ(target, executor->Query());
}
//测试化用例13：向南右转为西
TEST(ExecutorTest, should_return_facing_is_W_given_command_is_R_and_facing_is_S)
{
    // given
    std::unique_ptr<Executor> executor(Executor::NewExecutor({0, 0, 'S'}, CarsType::CAR));

    // when
    executor->Execute("R");

    // then
    const Pose target({0, 0, 'W'});
    ASSERT_EQ(target, executor->Query());
}

}  // namespace adas
